package us.mmapp;

import java.io.IOException;
import java.io.InputStream;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.auth.BasicScheme;
import org.json.JSONException;
import org.json.JSONObject;

import us.mmapp.providers.UsersDbManager;
import us.mmapp.util.ApplicationData;
import us.mmapp.util.HttpManager;
import us.mmapp.util.ServicesUtils;
import us.mmapp.util.TextUtils;
import us.mmapp.util.UIUtils;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
/**
 * Login Activity is an activity that logs the user in.
 * Checks if the user is in the phone database. And if it
 * not then it connects to the web server in order to authenticate
 * Then it updates the database if it is the case, and also update
 * the SharedPreferences.
 * 
 */
public class LoginActivity extends Activity {
	
	private String mUsername;
	private String mPassword;
	private long mUid;
	private ProgressDialog mProgress;
	private UsersDbManager mDbHelper;
	
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		
		mDbHelper = new UsersDbManager(this);
		mDbHelper.open();
		setContentView(R.layout.login_form);
		
		final TextView usernameBox = (TextView) findViewById(R.id.loginUsername);
		final TextView passwordBox = (TextView) findViewById(R.id.loginPassword);
		
		Button loginButton = (Button) findViewById(R.id.loginButton);
		Button resetButton = (Button) findViewById(R.id.resetButton);
		
		// Add Listener to the login button
		loginButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				// Get Username
				mUsername = usernameBox.getText().toString();
				//Get password
				mPassword = passwordBox.getText().toString();
				doLogin();
			}
		});
		
		// Add listener to the reset button
		Log.e("LOGIN", resetButton.toString());
		resetButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				usernameBox.setText("");
				passwordBox.setText("");
			}
		});
	}
	@Override
	public void onResume()
	{
		super.onResume();
		if (mDbHelper == null)
		{
			mDbHelper = new UsersDbManager(this);
			mDbHelper.open();
		}
	}
	@Override
	public void onStop()
	{
		super.onStop();
		if (mDbHelper != null)
		{
			mDbHelper.close();
			mDbHelper = null;
		}
	}
	/**
	 * Function to do the actual login after the user
	 * presses the login button.
	 */
	private void doLogin()
	{
		if (mPassword.length() == 0 || mUsername.length() == 0)
		{
			doneLogin(EMPTY_BOX_ERROR, null);
		}
		else
		{
			// Create the progressDialog
			mProgress = new ProgressDialog(this);
			mProgress.setMessage("Logging in...");
			mProgress.setIndeterminate(true);
			mProgress.setCancelable(false);
			// Show the progress while doing the work
			mProgress.show();
			
			//parameters, the progress values, and the final value of the task,
			AsyncTask<String, Void, JSONObject> t = new AsyncTask<String, Void, JSONObject>() {
				@Override
				protected JSONObject doInBackground(String... args) {
			    	JSONObject ret = null;
					try
					{
				    	HttpGet get = new HttpGet(ServicesUtils.LOGIN);
				    	
				    	get.addHeader(BasicScheme.authenticate(
				    			new UsernamePasswordCredentials(args[0],TextUtils.md5(args[1])),
				    			"UTF-8",
				    			false));
				    	
				    	HttpResponse httpResponse = HttpManager.execute(get);
				    	HttpEntity responseEntity = httpResponse.getEntity();
				    	
		                if (responseEntity != null)
		                {
	                        InputStream instream = responseEntity.getContent();
	                        String result = TextUtils.convertStreamToString(instream);           
	                        instream.close();
	                        // Try converting result to JSON
	                        Log.e("LOGIN", "Result: " + httpResponse);
	                        try {
								ret = new JSONObject(result);
							} catch (JSONException e) {
								Log.e("LOGIN", "Could not parse JSON.");
								ret = null;
							}
		                }
		                else
		                {
		                	Log.e("LOGIN", "Response Entity Null.");
		                }
					}
					catch (IOException e)
					{}
			    	
					return ret;
				}
				@Override
				protected void onPostExecute(JSONObject result) {
					if (result == null)
					{
						doneLogin(CONN_ERROR, null);
					}
					else
					{
						try {
							// Test if the error was set.
							result.get("error");
							doneLogin(SERVER_ERROR, result);
						} catch (JSONException e)
						{
							
							try {
								mUid = result.getLong("id");
							} catch (JSONException e1) {
								Log.e("LOGIN", e1.getMessage());
							}
							doneLogin(SUCCESS, result);
						}
					}
				}				
			};
			// Args needed for the working thread.
			String[] args = { mUsername, mPassword};
			t.execute(args);
		}
	}
	// Error codes for the login
	private final static int SUCCESS = 1;
	private final static int SERVER_ERROR = 2;
	private final static int EMPTY_BOX_ERROR = 3;
	private final static int CONN_ERROR = 4;
	
	/**
	 * Function called when the login part is done.
	 * 
	 * @param code the code it finished
	 */
	private void doneLogin(int code, JSONObject result)
	{
		switch (code)
		{
			case SUCCESS:
				// finish this Activity
				mProgress.dismiss();
				UIUtils.showToast(this, R.string.login_succ);
				
				// Mark shared preferences
			    SharedPreferences settings = getSharedPreferences("LOGIN", 0);
			    SharedPreferences.Editor editor = settings.edit();
			    editor.putString("username", mUsername);
			    editor.putString("password", mPassword);
			    editor.putLong("uid", mUid);
			    editor.putBoolean("loggedIn", true);
			    editor.commit();
			    // Announce the application data about login.
			    ApplicationData.logIn(mPassword, mUsername, mUid);
				finish();
				
				// Update the database with the user
				if (result != null)
				try {
					if (
					mDbHelper.updateUser(result.getLong("id"), result.getString("username"),
							mPassword, result.getString("email")) == false)
					{
						mDbHelper.createUser(result.getLong("id"), result.getString("username"),
							mPassword, result.getString("email"));
					}
				} catch (JSONException e1) {
					Log.e("LOGIN", "JSON parsing failed when result dispatched.");
				}
				catch (Exception e)
				{}
				break;
			case EMPTY_BOX_ERROR:
			{
				// Toast message
				UIUtils.showToast(this, R.string.login_empty_cred);
				break;
			}
			case SERVER_ERROR:
			{
				try
				{
					
					Toast t = Toast.makeText(getApplicationContext(), (String) result.getString("error"), Toast.LENGTH_LONG);
					Log.e("AICI: ", result.getString("error"));
					t.show();
				} catch (JSONException e) {}
				mProgress.dismiss();
				break;
			}
			case CONN_ERROR:
			{
				// Connection error can be saved if the user
				// logged in before using this phone
				if (mDbHelper != null)
				{
					Cursor cursor = mDbHelper.fetchUser(this.mUsername, this.mPassword);
					if (cursor != null && cursor.getCount() != 0)
					{
						mUid = cursor.getLong(cursor.getColumnIndex(UsersDbManager.KEY_ID));
						cursor.close();
						// found user that match
						doneLogin(SUCCESS, null);
						return;
					}
					if (cursor != null && !cursor.isClosed()) cursor.close();
					cursor = mDbHelper.fetchUser(this.mUsername);
					if (cursor != null && cursor.getCount() != 0)
					{
						cursor.close();
						// found user but incorrect password
						mProgress.dismiss();
						UIUtils.showToast(this, R.string.login_wrong_cred);
						return;
					}
					if (cursor != null) cursor.close();
				}
				// else report Connection error.
				mProgress.dismiss();
				UIUtils.showToast(this, R.string.login_conn_error);
				break;
			}
		}
	}
}
